﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Cache;
using System.IO;
using Task.Log;
using Task.DB;
using Task.Quartz.Execute.IExchange;
using Task.Util;
using System.Threading;
using System.Data;

namespace Task.Quartz.Execute.Holytax
{
    public class UpDate : ITaskExchange
    {
        private readonly Object lock_this_ = new Object();
        private SynParamEntity gogal = null;
        public void Run(SynParamEntity synParam)
        {
            try
            {
                this.gogal = synParam;
                for (int i = 0; i < 10; i++)
                {
                    NlogLogger.Default.Info("******任务【" + gogal.FileName + "-自动上传" + "】开始*******"
                  , System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                    Thread.Sleep(1000);
                }
                NlogLogger.Default.Info("******任务【" + gogal.FileName + "-自动上传" + "】开始*******"
                    , System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                //var Context = FluentDB.ContextSQL();
                //List<dynamic> account_EntList = Context.Sql(@"select * from Account_Ent where entid in(
                //                                    select distinct entid from Account_Ent2User 
                //                                    where LastReceiveTime <> ''
                //                                    )").QueryMany<dynamic>();
                //Run(account_EntList);
                Thread.Sleep(1000);

            }
            catch (Exception ex)
            {
                LogHelper.Info(ex.ToString(), System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            }
        }

        void Run(List<dynamic> List)
        {
            for (int i = 0; i < 10; i++)
            {
                LogHelper.Info("上传文件" + gogal.FileName, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                Thread.Sleep(1000);
            }
         
            //if (List.Count() <= 0)
            //{
            //    LogHelper.Info("不存在需要处理任务，自动退出！" + gogal.FileName, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            //    return;
            //}
            //System.Threading.CancellationTokenSource cts = new System.Threading.CancellationTokenSource();
            //System.Threading.Tasks.TaskFactory taskFactory = new System.Threading.Tasks.TaskFactory();
            //List<System.Threading.Tasks.Task> taskList = new List<System.Threading.Tasks.Task>();

            //foreach (var item in List)
            //{
            //    var EntID = item.EntID;
            //    var EntTaxCode = item.EntTaxCode;
            //    taskList.Add(taskFactory.StartNew(() => TaskDo(cts.Token, EntID, EntTaxCode), cts.Token));
            //}

            //taskFactory.ContinueWhenAll(taskList.ToArray(),
            //     TaskEnd
            //    , System.Threading.CancellationToken.None);
        }

        void TaskEnd(System.Threading.Tasks.Task[] tasks)
        {
            int loop = 0;
            foreach (System.Threading.Tasks.Task task in tasks)
            {
                if (task.IsCompleted)
                {
                    loop++;
                }
                else
                {
                    break;
                }
            }
            if (loop == tasks.Count())
            {
                LogHelper.Info("任务全部结束" + gogal.FileName, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            }
        }

        /// <summary>
        /// 执行函数需要有返回值
        /// </summary>
        /// <param name="ct"></param>
        /// <param name="InEntID"></param>
        /// <param name="InEntTaxCode"></param>
        /// <returns></returns>
        string TaskDo(System.Threading.CancellationToken ct, object InEntID, object InEntTaxCode)
        {
            lock (lock_this_)
            {
                try
                {
                    #region 数据处理

                    string savePath = string.Format(@"{0}\TempData\UpdateFile\", AppPathUtil.GetAssemblyDirPath());
                    if (!Directory.Exists(savePath))
                    {
                        Directory.CreateDirectory(savePath);
                    }

                    var Context = FluentDB.ContextSQL();
                    int numberOfaccount_EntList = Context.Sql("select count(pkid) from INV_VAT where buyer =@0 and statusId in( '01','02') ").Parameters(InEntTaxCode).QuerySingle<int>();
                    if (numberOfaccount_EntList == 0)
                    {
                        LogHelper.Debug("税号【" + InEntTaxCode + "】无需要发送数据,自动退出。", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                        return null;
                    }

                    string EntID = InEntID.ToString();
                    string entTaxCode = InEntTaxCode.ToString();
                    dynamic Account_Ent = Context.Sql("select * from Account_Ent where EntID = @0 ").Parameters(EntID).QuerySingle<dynamic>();

                    LogHelper.Info("处理税号=" + InEntTaxCode, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                    ExchangeEntity exEntity = MemoryCacheHelper.GetCacheItem("key_TaskDo_" + entTaxCode, delegate()
                    {
                        INIFileUtil ini = new INIFileUtil(AppDomain.CurrentDomain.BaseDirectory + "/Configs/config_Holytax.ini");
                        return new ExchangeEntity(entTaxCode,
                                        ini.IniReadValue("param", "PFAccount"),
                                        ini.IniReadValue("param", "PFPassword"),
                                        ini.IniReadValue("param", "ServerAddress") + ini.IniReadValue("param", "UpURL"),
                                        "",
                                        "",
                                        ini.IniReadValue("param", "IsProxy"),
                                        ini.IniReadValue("param", "ProxyIp"),
                                        ini.IniReadValue("param", "ProxyPort"),
                                        ini.IniReadValue("param", "AuthUID"),
                                        ini.IniReadValue("param", "AuthPassword"));
                    }, new TimeSpan(0, 60 * 60, 0));

                    #region 数据提取
                    List<dynamic> delQueryable = null;
                    List<dynamic> vatQueryable = null;

                    string __BuyerName = Account_Ent.EntName;
                    string saveFileNameTemp = string.Format("{0}", entTaxCode + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + RandomValue.GetRandomNumber(6));
                    string saveFileName = string.Format("{0}\\{1}.xml", savePath, saveFileNameTemp);
                    bool bXmlFileBuildResult = VATXmlFileBuilder(entTaxCode, __BuyerName, saveFileName, out delQueryable, out vatQueryable);
                    if (!bXmlFileBuildResult)
                    {
                        LogHelper.Error("生成XML文件失败!", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                        return null;
                    }
                    LogHelper.Debug("执行Zip压缩", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                    //执行Zip压缩
                    string strZipFilePath = saveFileName.Replace(".xml", ".zip");
                    int iZipResult = ZipHelper.ZipFile(saveFileName, strZipFilePath);
                    if (iZipResult != 1)
                    {
                        LogHelper.Error("压缩失败!", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                        return null;
                    }
                    LogHelper.Debug("执行Http上传", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                    //执行Http上传
                    bool bResult = InvoiceExchangeHelper.UploadZips(exEntity, strZipFilePath);
                    if (!bResult)
                    {
                        LogHelper.Error(exEntity.ErrorDesc, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                        return null;
                    }

                    LogHelper.Info("更新发票状态", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                    //更新发票状态
                    using (var contextTran = FluentDB.ContextSQL().UseTransaction(true))
                    {
                        foreach (var delInvoice in delQueryable)
                        {
                            object tem = delInvoice.pkid;
                            contextTran.Update("INV_VAT_DEL")
                                .Column("sendDate", DateTime.Now.ToString("yyyyMMddHHmmss"))
                                .Column("sendFileName", strZipFilePath)
                                .Column("hasSent", 2)
                                .Where("pkid", tem)
                                .Execute();
                        }
                        contextTran.Commit();
                    }
                    StringBuilder sb = new StringBuilder();
                    using (var contextTran = FluentDB.ContextSQL().UseTransaction(true))
                    {
                        foreach (var vatInvoice in vatQueryable)
                        {
                            object tem = vatInvoice.pkid;
                            string temp = vatInvoice.rtTempNo;
                            int rt = 0;
                            int.TryParse(temp, out rt);
                            string valueCount = vatInvoice.statusId != "03" ? (rt + 1).ToString() : temp;//保存认证次数

                            contextTran.Update("INV_VAT")
                                    .Column("statusId", "03")
                                    .Column("sendDate", DateTime.Now.ToString("yyyyMMddHHmmss"))
                                    .Column("sendFileName", strZipFilePath)
                                    .Column("hasSent", 1)
                                    .Column("authStatus", "01")
                                    .Column("rtTempNo", valueCount)
                                    .Where("pkid", tem)
                                    .Execute();
                        }
                        contextTran.Commit();

                        foreach (var vatInvoice in vatQueryable)
                        {
                            sb.AppendFormat("发票代码:{0}，发票号码：{1}\r\n", vatInvoice.invoiceCode, vatInvoice.invoiceNo);
                        }
                    }
                    LogHelper.Debug(sb.ToString(), System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                    LogHelper.Info("上传完成！", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

                    File.Delete(saveFileName);
                    File.Delete(strZipFilePath);

                    #endregion

                    #endregion

                    return null;
                }
                catch (Exception exe)
                {
                    LogHelper.Info(exe.Message, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                    return null;
                }
            }
        }

        #region 生成XML文件
        private bool VATXmlFileBuilder(string strBuyer, string strBuyerName, string xmlFilePath, out List<dynamic> delQueryable, out List<dynamic> vatQueryable)
        {
            var Context = FluentDB.ContextSQL();
            delQueryable = Context.Sql("select * from INV_VAT_DEL where buyer=@0 and hasSent=1").Parameters(strBuyer).QueryMany<dynamic>();
            vatQueryable = Context.Sql("select * from INV_VAT where buyer=@0 and statusId in( '01','02')").Parameters(strBuyer).QueryMany<dynamic>();

            #region

            XmlFileBuilder xmlFile = new XmlFileBuilder(xmlFilePath);

            //构造HEAD节点
            Dictionary<string, string> dicHead = new Dictionary<string, string>();
            dicHead.Add("code", "RZ00100");
            dicHead.Add("title", "增值税专用发票抵扣联信息企业采集待认证数据_");
            dicHead.Add("nsr", strBuyer);
            dicHead.Add("qymc", strBuyerName);
            dicHead.Add("scrq", DateTime.Now.ToString("yyyyMMdd"));
            bool bHeaderBuilder = xmlFile.HeaderBuilder(dicHead);
            if (!bHeaderBuilder)
            {
                return false;
            }

            int iRowIndex = 0;
            //构造ROW节点
            if (delQueryable.Count() > 0)
            {
                #region
                Dictionary<string, string> dicVatDel = new Dictionary<string, string>();
                List<Dictionary<string, string>> listDicGoodsInfoDel = new List<Dictionary<string, string>>();
                foreach (var invVatDel in delQueryable)
                {
                    iRowIndex++;
                    dicVatDel.Clear();
                    dicVatDel.Add("yxbz", "0");
                    dicVatDel.Add("dm", invVatDel.invoiceCode);
                    dicVatDel.Add("hm", invVatDel.invoiceNo);
                    dicVatDel.Add("gf", invVatDel.buyer);
                    dicVatDel.Add("xf", invVatDel.seller);
                    dicVatDel.Add("kr", invVatDel.opentime);
                    dicVatDel.Add("je", invVatDel.amount.ToString());
                    dicVatDel.Add("se", invVatDel.taxAmount.ToString());
                    dicVatDel.Add("sl", invVatDel.taxPoint);
                    dicVatDel.Add("mw", invVatDel.ciphertext);
                    dicVatDel.Add("bb", "01");

                    dicVatDel.Add("mytx", invVatDel.mytx);
                    dicVatDel.Add("jqbh", invVatDel.jqbh);
                    dicVatDel.Add("jqbm", invVatDel.jqbh);//后加，兼容以前的后台接口

                    dicVatDel.Add("smsj", string.Format("{0}-{1}-{2} {3}:{4}:{5}",
                        invVatDel.inputDate.Substring(0, 4),
                        invVatDel.inputDate.Substring(4, 2),
                        invVatDel.inputDate.Substring(6, 2),
                        invVatDel.inputDate.Substring(8, 2),
                        invVatDel.inputDate.Substring(10, 2),
                        invVatDel.inputDate.Substring(12, 2)));
                    dicVatDel.Add("inusr", invVatDel.inputMan);
                    dicVatDel.Add("lsh", invVatDel.tempNoInBatch.ToString());
                    dicVatDel.Add("fplx", invVatDel.internalTypeId);
                    dicVatDel.Add("fpzl", invVatDel.invoiceVariety);
                    dicVatDel.Add("fpbz", invVatDel.remark);
                    dicVatDel.Add("rzfs", "0");
                    dicVatDel.Add("fpmdh", invVatDel.shopNo);
                    dicVatDel.Add("fpdklx", invVatDel.openType);
                    dicVatDel.Add("dksbh", invVatDel.dkTaxcode);
                    dicVatDel.Add("scanpc", invVatDel.batchNo);
                    dicVatDel.Add("fpiszk", "0");
                    dicVatDel.Add("fpzklv", "0");
                    dicVatDel.Add("fpzkje", invVatDel.discountAmount == null ? "" : invVatDel.discountAmount.ToString());
                    dicVatDel.Add("isrz", "0");
                    dicVatDel.Add("imagepath", invVatDel.imagePath);//wlw 2014-12-30 添加
                    dicVatDel.Add("hzfw", invVatDel.ciphertextType.Equals("02") ? "1" : "0");
                    dicVatDel.Add("wdh", invVatDel.branchNo);//wlw 2014-02-17 添加
                    //（华润费用类需要的条形码）
                    dicVatDel.Add("txm", invVatDel.CostBarCode);
                    listDicGoodsInfoDel.Clear();

                    if (invVatDel.ciphertextType.Equals("02"))
                    {
                        object pkid = invVatDel.pkid;
                        IList<dynamic> delGoodsQueryable = Context.Sql("select * from INV_VATGOODSINFO_DEL where invoicePkid=@0").Parameters(pkid).QueryMany<dynamic>();
                        if (delGoodsQueryable.Count() > 0)
                        {
                            Dictionary<string, string> dicDelGoods = new Dictionary<string, string>();
                            foreach (var delGoods in delGoodsQueryable)
                            {
                                dicDelGoods = new Dictionary<string, string>();//解决原来字典清空造成外层List存取值错误
                                dicDelGoods.Add("wpmc", delGoods.goodsName.Replace("\0", ""));
                                dicDelGoods.Add("wpdw", delGoods.goodsUnit.Replace("\0", ""));
                                dicDelGoods.Add("wpsl", delGoods.goodsQty.Replace("\0", ""));
                                listDicGoodsInfoDel.Add(dicDelGoods);
                            }
                        }
                        dicVatDel.Add("xfmc", invVatDel.sellerName ?? invVatDel.sellerName.Replace("\0", ""));
                        dicVatDel.Add("gfmc", invVatDel.buyerName ?? invVatDel.buyerName.Replace("\0", ""));
                        dicVatDel.Add("fp2code", invVatDel.ciphertext1);
                        dicVatDel.Add("wphs", delGoodsQueryable.Count().ToString());

                    }
                    bool bRowBuilder = xmlFile.RowBuilder(dicVatDel, iRowIndex.ToString(), invVatDel.ciphertextType, listDicGoodsInfoDel);
                    if (!bRowBuilder)
                    {
                        return false;
                    }
                }
                #endregion
            }

            #region
            Dictionary<string, string> dicVat = new Dictionary<string, string>();
            List<Dictionary<string, string>> listDicGoodsInfo = new List<Dictionary<string, string>>();
            foreach (var invVat in vatQueryable)
            {
                iRowIndex++;
                dicVat.Clear();
                dicVat.Add("yxbz", "1");
                dicVat.Add("dm", invVat.invoiceCode);
                dicVat.Add("hm", invVat.invoiceNo);
                dicVat.Add("gf", invVat.buyer);
                dicVat.Add("xf", invVat.seller);
                dicVat.Add("kr", invVat.opentime);
                dicVat.Add("je", invVat.amount.ToString());
                dicVat.Add("se", invVat.taxAmount.ToString());
                dicVat.Add("sl", invVat.taxPoint);
                dicVat.Add("mw", invVat.ciphertext);
                dicVat.Add("bb", "01");

                dicVat.Add("mytx", invVat.mytx);
                dicVat.Add("jqbh", invVat.jqbh);
                dicVat.Add("jqbm", invVat.jqbh);//后加，兼容以前的后台接口

                dicVat.Add("smsj", string.Format("{0}-{1}-{2} {3}:{4}:{5}",
                        invVat.inputDate.Substring(0, 4),
                        invVat.inputDate.Substring(4, 2),
                        invVat.inputDate.Substring(6, 2),
                        invVat.inputDate.Substring(8, 2),
                        invVat.inputDate.Substring(10, 2),
                        invVat.inputDate.Substring(12, 2)));
                dicVat.Add("inusr", invVat.inputMan);
                dicVat.Add("lsh", invVat.tempNoInBatch.ToString());
                dicVat.Add("fplx", invVat.internalTypeId);
                dicVat.Add("fpzl", invVat.invoiceVariety);
                dicVat.Add("fpbz", invVat.remark);
                dicVat.Add("rzfs", "0");
                dicVat.Add("fpmdh", invVat.shopNo);
                dicVat.Add("fpdklx", invVat.openType);
                dicVat.Add("dksbh", invVat.dkTaxcode);
                dicVat.Add("scanpc", invVat.batchNo);
                dicVat.Add("fpiszk", "0");
                dicVat.Add("fpzklv", "0");
                dicVat.Add("fpzkje", invVat.discountAmount == null ? "" : invVat.discountAmount.ToString());
                dicVat.Add("isrz", "0");
                dicVat.Add("imagepath", invVat.imagePath);//wlw 2014-12-30 添加
                dicVat.Add("hzfw", invVat.ciphertextType.Equals("02") ? "1" : "0");
                dicVat.Add("wdh", invVat.branchNo);//wlw 2014-02-17 添加
                //（华润费用类需要的条形码）
                dicVat.Add("txm", invVat.CostBarCode);
                listDicGoodsInfo.Clear();

                if (invVat.ciphertextType.Equals("02"))
                {
                    object pkid = invVat.pkid;
                    IList<dynamic> goodsQueryable = Context.Sql("select * from INV_VATGOODSINFO_DEL where invoicePkid=@0").Parameters(pkid).QueryMany<dynamic>();
                    if (goodsQueryable.Count() > 0)
                    {
                        Dictionary<string, string> dicGoods = null;
                        foreach (var goods in goodsQueryable)
                        {
                            dicGoods = new Dictionary<string, string>();//解决原来字典清空造成外层List存取值错误
                            dicGoods.Add("wpmc", UTF8ToUnicode(goods.goodsName.Replace("\0", "")));
                            dicGoods.Add("wpdw", UTF8ToUnicode(goods.goodsUnit.Replace("\0", "")));
                            dicGoods.Add("wpsl", UTF8ToUnicode(goods.goodsQty.Replace("\0", "")));
                            listDicGoodsInfo.Add(dicGoods);
                        }
                    }
                    dicVat.Add("xfmc", UTF8ToUnicode(invVat.sellerName.Replace("\0", "")));
                    dicVat.Add("gfmc", UTF8ToUnicode(invVat.buyerName.Replace("\0", "")));
                    dicVat.Add("fp2code", invVat.ciphertext1);
                    dicVat.Add("wphs", goodsQueryable.Count().ToString());

                }
                bool bRowBuilder = xmlFile.RowBuilder(dicVat, iRowIndex.ToString(), invVat.ciphertextType, listDicGoodsInfo);
                if (!bRowBuilder)
                {
                    return false;
                }
            }
            #endregion

            if (!xmlFile.XmlFileBuilderFinish())
            {
                return false;
            }
            return true;
            #endregion
        }

        // 转换接收到的字符串 
        private static string UTF8ToUnicode(string recvStr)
        {
            try
            {
                byte[] tempStr = Encoding.UTF8.GetBytes(recvStr);
                byte[] tempDef = Encoding.Convert(Encoding.UTF8, Encoding.Default, tempStr);
                string msgBody = Encoding.Default.GetString(tempDef);
                return msgBody.Replace("?", "");
            }
            catch (Exception ex)
            {
                return recvStr;
            }
        }
        #endregion

    }
}
